package avicit.bdp.dgs.standard.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.EntityUtils;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.core.enums.DataStateEnum;
import avicit.bdp.dgs.standard.dao.LookupTableValueDao;
import avicit.bdp.dgs.standard.dto.DataElementDto;
import avicit.bdp.dgs.standard.dto.LookupTableDto;
import avicit.bdp.dgs.standard.dto.LookupTableValueDto;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.Page;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author mayi 值域标准服务层
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class LookupTableValueService extends BaseService<LookupTableValueDao, LookupTableValueDto> {

  @Resource private LookupTableValueDao lookupTableValueDao;

  @Resource private ConvertColumnClient convertColumnClient;

  @Resource private DataElementService dataElementService;

  @Resource private LookupTableService lookupTableService;

  public QueryRespBean<LookupTableValueDto> getPageList(
      String lookupTableId, String keyWords, Integer pageNo, Integer pageSize) throws Exception {

    QueryRespBean<LookupTableValueDto> queryRespBean = new QueryRespBean<>();
    com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);

    Page<LookupTableValueDto> page = this.lookupTableValueDao.getPageList(lookupTableId, keyWords);
    try {
      valueConvert(page);
    } catch (Exception e) {
      e.printStackTrace();
    }
    queryRespBean.setResult(page);
    BdpLogUtil.log4Query(queryRespBean);
    return queryRespBean;
  }

  public List<LookupTableValueDto> selectByLookupTableId(String lookupTableId) {
    return this.mapper.selectListByLookupTableId(lookupTableId);
  }

  private void valueConvert(Page<LookupTableValueDto> page) {
    // 循环组装请求数据
    Map<String, Set<String>> convertFormData = new HashMap<>(16);
    for (LookupTableValueDto lookupTableValueDto : page) {
      BusinessUtil.createConvertSet(
          convertFormData, SystemConstant.USER, lookupTableValueDto.getCreatedBy());
    }
    if (convertFormData.size() > 0) {
      // 获取请求结果
      Map<String, Map<String, String>> convertResultData =
          convertColumnClient.replace(convertFormData);
      // 循环设置Alias或Name的值
      for (LookupTableValueDto lookupTableValueDto : page) {
        lookupTableValueDto.setCreatedBy(
            BusinessUtil.convertFormat(
                convertResultData, SystemConstant.USER, lookupTableValueDto.getCreatedBy()));
      }
    }
  }

  public void deleteByLookupTableId(String lookupTableId) {
    this.lookupTableValueDao.deleteByLookupTableId(lookupTableId);
  }

  public void update(LookupTableValueDto lookupTableValueDto) {
    CheckParaUtils.checkObjectValidity(lookupTableValueDto.getId(), logger, "ID不能为空");
    CheckParaUtils.checkObjectValidity(
        lookupTableValueDto.getLookupTableId(), logger, "值域标准ID不能为空");
    CheckParaUtils.checkObjectValidity(lookupTableValueDto.getValue(), logger, "代码值必填");
    CheckParaUtils.checkStringValidity(lookupTableValueDto.getName(), logger, "名称必填");

    LookupTableValueDto oldLookupTableValue = this.selectByPrimaryKey(lookupTableValueDto.getId());
    CheckParaUtils.checkDbObjectValidity(
        oldLookupTableValue,
        logger,
        String.format("没有查到数据，请确保id:%s的数据是否存在", lookupTableValueDto.getId()));

    // 校验标准名称唯一性
    if (!lookupTableValueDto.getName().equals(oldLookupTableValue.getName())) {
      checkNameUnique(lookupTableValueDto);
    }

    // 校验标准编码唯一性
    if (!lookupTableValueDto.getValue().equals(oldLookupTableValue.getValue())) {
      checkValueUnique(lookupTableValueDto);
    }

    lookupTableValueDto.setCreationDate(oldLookupTableValue.getCreationDate());
    this.updateByPrimaryKey(lookupTableValueDto);
    BdpLogUtil.log4Update(lookupTableValueDto, oldLookupTableValue);
  }

  public Boolean batchDelete(String ids) {
    CheckParaUtils.checkStringValidity(ids, logger, "没有传入待删除的ID");
    String[] idArr = ids.split(Constants.COMMA);
    for (String id : idArr) {
      LookupTableValueDto lookupTableValueDto = this.selectByPrimaryKey(id);
      CheckParaUtils.checkDbObjectValidity(
          lookupTableValueDto, logger, String.format("没有查到数据，请确保id:%s的数据是否存在", id));

      // todo 已经被引用的值域标准，不允许直接删除，给出提示:该值域标准已经被引用，不能删除
      // 值域标准状态为已发布，不允许删除
      LookupTableDto lookupTableDto =
          lookupTableService.selectByPrimaryKey(lookupTableValueDto.getLookupTableId());
      CheckParaUtils.checkDbObjectValidity(lookupTableDto, logger, "没有查到对应的值域标准记录");
      if (lookupTableDto.getStatus() != null
          && lookupTableDto.getStatus() == DataStateEnum.PUBLISHED.getCode()) {
        throw new BusinessException("该值域标准状态为已发布，不能删除");
      }

      // 统计值域标准在数据元中的引用
      DataElementDto dataElementDto = new DataElementDto();
      dataElementDto.setLookupTableId(lookupTableValueDto.getLookupTableId());
      List<DataElementDto> dataElementList = dataElementService.selectList(dataElementDto);
      if (CollectionUtils.isNotEmpty(dataElementList)) {
        List<String> dataElementNames =
            dataElementList.stream().map(DataElementDto::getName).collect(Collectors.toList());
        throw new BusinessException(
            "该值域标准已经被[" + String.join(",", dataElementNames) + "]等数据项标准引用，不能删除!");
      }

      this.mapper.deleteByPrimaryKey(id);
      // 记录日志
      BdpLogUtil.log4Delete(lookupTableValueDto);
    }

    return true;
  }

  /**
   * 校验名称唯一性
   *
   * @param lookupTableValueDto 检测对象
   */
  private void checkNameUnique(LookupTableValueDto lookupTableValueDto) {
    if (lookupTableValueDto != null) {
      if (StringUtils.isEmpty(lookupTableValueDto.getName())) {
        throw new BusinessException("名称不能为空");
      }

      LookupTableValueDto paramName = new LookupTableValueDto();
      paramName.setLookupTableId(lookupTableValueDto.getLookupTableId());
      paramName.setName(lookupTableValueDto.getName());
      if (this.selectCount(paramName) > 0) {
        throw new BusinessException("名称[" + lookupTableValueDto.getName() + "]已存在");
      }
    }
  }

  /**
   * 校验代码值唯一性
   *
   * @param lookupTableValueDto 检测对象
   */
  private void checkValueUnique(LookupTableValueDto lookupTableValueDto) {
    if (lookupTableValueDto != null) {
      if (StringUtils.isEmpty(lookupTableValueDto.getValue())) {
        throw new BusinessException("代码值不能为空");
      }

      LookupTableValueDto paramValue = new LookupTableValueDto();
      paramValue.setValue(lookupTableValueDto.getValue());
      paramValue.setLookupTableId(lookupTableValueDto.getLookupTableId());
      if (this.selectCount(paramValue) > 0) {
        throw new BusinessException("代码值[" + lookupTableValueDto.getValue() + "]已存在");
      }
    }
  }

  public void batchSave(List<LookupTableValueDto> list) {
    if (CollectionUtils.isNotEmpty(list)) {

      List<LookupTableValueDto> saveList = new ArrayList<>();
      List<LookupTableValueDto> updateList = new ArrayList<>();

      for (LookupTableValueDto lookupTableValueDto : list) {

        CheckParaUtils.checkObjectValidity(
            lookupTableValueDto.getLookupTableId(), logger, "值域标准ID不能为空");

        if (StringUtils.isNotEmpty(lookupTableValueDto.getId())) {
          updateList.add(lookupTableValueDto);
        } else {
          checkNameUnique(lookupTableValueDto);
          checkValueUnique(lookupTableValueDto);
          lookupTableValueDto.setId(ComUtil.getId());
          EntityUtils.setCreateInfo(lookupTableValueDto);
          saveList.add(lookupTableValueDto);
        }
      }

      if (CollectionUtils.isNotEmpty(saveList)) {
        this.lookupTableValueDao.batchSave(saveList);
      }

      if (CollectionUtils.isNotEmpty(updateList)) {
        for (LookupTableValueDto lookupTableValueDto : updateList) {
          this.update(lookupTableValueDto);
        }
      }
    }
    String logTitle = "新增/修改值域标准码值：【" + JSONObject.toJSONString(list) + "】";
    BdpLogUtil.log("值域标准模块", logTitle, PlatformConstant.OpType.insert);
  }

  public List<String> getValueList(String lookupTableId) {
    return this.lookupTableValueDao.getValueList(lookupTableId);
  }
}
